'use strict';

// IP 锁的键值前缀
const IP_LOOK_NUM_KEY = 'IP_LOOK_NUM_KEY';

module.exports = () => {
  return async function(ctx, next) {
    const { redis } = ctx.app;
    const { url } = ctx.req;
    // 获取客户端的IP地址
    const clientIP = ctx.req.headers['x-forwarded-for'];
    // redis 存储的键值
    const IP_KEY = `${IP_LOOK_NUM_KEY}:${clientIP}:${url}`;
    // 获取 redis 缓存的数据
    const catchData = await redis.get(IP_KEY);
    const { maxNum, maxTime, cacheTime } = ctx.app.config.fullIP.cusOpt;
    let saveData: any = null;
    if (catchData) {
      saveData = JSON.parse(catchData);
    } else {
      // 设置初始化数据
      const timeNum = new Date().getTime();
      saveData = {
        timeNum,
        ipNum: 0,
      };
    }
    // 每次请求 + 1
    saveData.ipNum += 1;
    // 判断请求总次数是否大于30
    if (saveData.ipNum > maxNum) {
      const currentTime = new Date().getTime();
      const chaTime = currentTime - saveData.timeNum;
      // 如果在5秒内请求次数大于50 就锁定当前IP
      if (chaTime < maxTime) {
        ctx.addIP(clientIP);
      } else {
        saveData.timeNum = currentTime;
        saveData.ipNum = 1;
      }
    }
    await redis.set(IP_KEY, JSON.stringify(saveData), 'EX', cacheTime);
    await next();
  };
};
